home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / What's New? / Development Kits / Mac OS / USB DDK 1.4.6f4 / Examples / CompositeClassDriver / CompositeClassDriver.c next >
Encoding:
C/C++ Source or Header  |  2000-09-25  |  28.2 KB  |  801 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        CompositeClassDriver.c
  3.  
  4.     Contains:    Core functionality to Composite Class Driver
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1997-2000 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Types.h>
  13. #include <Devices.h>
  14. #include <processes.h>
  15. #include <DriverServices.h>
  16. #include <USB.h>
  17.  
  18. #include "CompositeClassDriver.h"
  19.  
  20. // USB_LOCATION_FLAG should be true if we're being compiled into ROM
  21. #ifndef USB_LOCATION_FLAG
  22.     #define USB_LOCATION_FLAG 0
  23. #endif
  24.  
  25.  
  26. #define debugBuild 0
  27.  
  28. #if debugBuild
  29. #define debugLevel 2
  30. #define debugStatus(ref, str, val) USBExpertStatusLevel(debugLevel, ref, kCompositeDriverName str, val);
  31. #else
  32. #define debugLevel 5
  33. #define debugStatus(ref, str, val) 
  34. #endif
  35.  
  36. usbCompositePBStruct newInterfacesPB;
  37.  
  38. static Boolean isPowerOf10(UInt32 n)    // Use this to calm down grossly repeating messages. Only goes at 1, 10, 100 etc
  39. {
  40.     if(n <= 1)
  41.     {
  42.         return(true);
  43.     }
  44.     while(n > 10)
  45.     {
  46.         if( (n %10) != 0)
  47.         {
  48.             return(false);
  49.         }
  50.         n /= 10;
  51.     }
  52.     return(n == 10);
  53. }
  54.  
  55. void InitParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock)
  56. {
  57.     paramblock->usbReference = theDeviceRef;
  58.     paramblock->usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  59.     paramblock->pbLength = sizeof(usbCompositePBStruct);
  60.     paramblock->pbVersion = kUSBCurrentPBVersion;
  61.     paramblock->usb.cntl.WIndex = 0;             
  62.     paramblock->usbBuffer = nil;        
  63.     paramblock->usbStatus = kUSBNoErr;
  64.     paramblock->usbReqCount = 0;
  65.     paramblock->usbActCount = 0;
  66.     paramblock->usb.cntl.WValue = 0;
  67.     paramblock->usbFlags = 0;
  68. }
  69.  
  70. /*
  71.     This is copied wholesale from the UIM via the hub driver. 
  72.  
  73.   This table contains the list of errata that are necessary for known problems with particular hub
  74.   The format is vendorID, product ID, lowest revisionID needing errata, highest rev needing errata, errataBits
  75.   The result of all matches is ORed together, so more than one entry may match.  Typically for a given errata a
  76.   list of hubs revisions that this applies to is supplied.
  77. */
  78. enum{
  79.     kErrataNoReset = 1
  80.     };
  81.  
  82. typedef struct {
  83.     UInt16                         vendID;
  84.     UInt16                         deviceID;
  85.     UInt16                         revisionLo;
  86.     UInt16                         revisionHi;
  87.     UInt32                         errata;
  88. }ErrataListEntry;
  89.  
  90. static ErrataListEntry    errataList[] = {
  91.  
  92. /* For the Cherry 3 port KB, radar 2358706
  93.  
  94.     With the composite driver doing a reset as its first action
  95.     (fixes a mass storage problem, but sounds like a bad idea)
  96.     the Cherry 3 prot KB does not work at boot, but does if 
  97.     hot plugged. It looks like all the resets at composite
  98.     replacement are sending it screwy. It looks to be 
  99.     working fine, but never gives any status change on its
  100.     interrupt endpoint.
  101.     
  102. */
  103.     {0x046a, 0x001, 0x0000, 0x9999, kErrataNoReset} // Cherry 3 port KB
  104. };
  105.  
  106. #define errataListLength (sizeof(errataList)/sizeof(ErrataListEntry))
  107.  
  108. static UInt32 GetErrataBits(USBDeviceDescriptor *desc)
  109. {
  110.     UInt32                vendID, deviceID, revisionID;
  111.     ErrataListEntry        *entryPtr;
  112.     UInt32                i, errata = 0;
  113.     
  114.     // get this chips vendID, deviceID, revisionID
  115.     vendID = USBToHostWord(desc->vendor);
  116.     deviceID = USBToHostWord(desc->product);
  117.     revisionID = USBToHostWord(desc->devRel);
  118.  
  119.     for(i=0, entryPtr = errataList; i<errataListLength; i++, entryPtr++){
  120.         if (vendID == entryPtr->vendID && deviceID == entryPtr->deviceID &&
  121.             revisionID >= entryPtr->revisionLo && revisionID <= entryPtr->revisionHi){
  122.                 errata |= entryPtr->errata;  // we match, add this errata to our list
  123.         }
  124.     }
  125.     return(errata);
  126. }
  127.  
  128.  
  129. Boolean immediateError(OSStatus err)
  130. {
  131.     return((err != kUSBPending) && (err != kUSBNoErr) );
  132. }
  133.  
  134. void CompositeDeviceInitiateTransaction(USBPB *pb)
  135. {
  136. register usbCompositePBStruct *pCompositePB;
  137. OSStatus myErr;
  138.  
  139.     pCompositePB = (usbCompositePBStruct *)(pb);
  140.  
  141.     if (pCompositePB->expertTerminatePending)                // TCC <USB16>
  142.         return;
  143.         
  144.     pCompositePB->transDepth++;
  145.     if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1))
  146.     {
  147.     
  148.         USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": Illegal Transaction Depth", pCompositePB->pb.usbRefcon);
  149.     }
  150.     
  151.     if (pCompositePB->driverRemovalPending)
  152.     {
  153.         pCompositePB->pb.usbRefcon = kReturnFromDriver;
  154.         return;
  155.     }
  156.  
  157.     switch(pCompositePB->pb.usbRefcon & ~kRetryTransaction)
  158.     {
  159.         case kResetDevice:
  160.     debugStatus(pCompositePB->pb.usbReference, ": kResetDevice resetting ", newInterfacesPB.busPowerAvailable);
  161.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  162.             pCompositePB->pb.usbRefcon |= kCompletionPending;
  163.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  164.             myErr = USBResetDevice(pb);
  165.             if(immediateError(myErr))
  166.             {
  167.                 pCompositePB->pb.usbRefcon &= ~kCompletionPending;
  168.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": kResetDevice - immediate error", myErr);
  169.             }
  170.             break;
  171.  
  172.         case kGetAConfiguration:
  173.     debugStatus(pCompositePB->pb.usbReference, ": kGetAConfiguration getting ", newInterfacesPB.busPowerAvailable);
  174.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  175.             
  176.             // Find the first configuration with any interface which satisfy the power requirements
  177.             pCompositePB->pb.usbReqCount = newInterfacesPB.busPowerAvailable;             
  178.             pCompositePB->pb.usbClassType = 0;             
  179.             pCompositePB->pb.usbSubclass = 0;             
  180.             pCompositePB->pb.usbProtocol = 0;             
  181.             pCompositePB->pb.usb.cntl.WValue = 0;             
  182.             pCompositePB->pb.usb.cntl.WIndex = 0;             
  183.             pCompositePB->pb.usbOther = 0xff;         // Find primary interface, not alts
  184.             
  185.             
  186.             pCompositePB->pb.usbRefcon |= kCompletionPending;        
  187.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  188.             myErr = USBFindNextInterface(pb);
  189.             if(immediateError(myErr))
  190.             {
  191.                 pCompositePB->pb.usbRefcon &= ~kCompletionPending;
  192.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": USBFindNextInterface (#1) - immediate error", myErr);
  193.             }
  194.             break;
  195.         
  196.         case kSetConfig:
  197.     debugStatus(pCompositePB->pb.usbReference, ": kSetConfig setting ", pCompositePB->currentConfiguration);
  198.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  199.             pCompositePB->pb.usb.cntl.WValue = pCompositePB->currentConfiguration;
  200.  
  201.             pCompositePB->pb.usbRefcon |= kCompletionPending;            
  202.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  203.             myErr = USBSetConfiguration(pb);
  204.             if(immediateError(myErr))
  205.             {
  206.                 pCompositePB->pb.usbRefcon &= ~kCompletionPending;
  207.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": USBSetConfiguration - immediate error", myErr);
  208.             }
  209.             break;
  210.             
  211.         case kAllocInterfaces:
  212.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  213.             pCompositePB->pb.usbReqCount = pCompositePB->interfaceCount * sizeof(interface);
  214.     debugStatus(pCompositePB->pb.usbReference, ": kAllocInterfaces allocating ", pCompositePB->pb.usbReqCount);
  215.             
  216.             pCompositePB->pb.usbRefcon |= kCompletionPending;            
  217.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  218.             myErr = USBAllocMem(pb);
  219.             if(immediateError(myErr))
  220.             {
  221.                 pCompositePB->pb.usbRefcon &= ~kCompletionPending;
  222.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": USBAllocMem - immediate error", myErr);
  223.             }
  224.             break;
  225.                 
  226.         case kGetConfigDesc:
  227.     debugStatus(pCompositePB->pb.usbReference, ": kGetConfigDesc new ", pCompositePB->currentConfiguration);
  228.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  229.  
  230.             pCompositePB->pb.usb.cntl.WValue = pCompositePB->currentConfiguration;
  231.             pCompositePB->pb.usbBuffer = &pCompositePB->configDescriptor;     // put it here
  232.             pCompositePB->pb.usbReqCount = sizeof(USBConfigurationDescriptor);     // at most this size
  233.  
  234.             pCompositePB->pb.usbRefcon |= kCompletionPending;
  235.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  236.             myErr = USBGetConfigurationDescriptor(pb);
  237.             if(immediateError(myErr))
  238.             {
  239.                 pCompositePB->pb.usbRefcon &= ~kCompletionPending;
  240.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": USBGetConfigurationDescriptor - immediate error", myErr);
  241.             }
  242.     
  243.             break;
  244.  
  245.         case kSetRemoteWakeup:            
  246.     debugStatus(pCompositePB->pb.usbReference, ": kSetRemoteWakeup doing", pCompositePB->pb.usbReference);
  247.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  248.             
  249.             pCompositePB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBDevice);            
  250.             
  251.             pCompositePB->pb.usb.cntl.BRequest = kUSBRqSetFeature;
  252.             pCompositePB->pb.usb.cntl.WValue = kUSBFeatureDeviceRemoteWakeup; 
  253.             pCompositePB->pb.usb.cntl.WIndex = 0;
  254.             
  255.             pCompositePB->pb.usbRefcon |= kCompletionPending;
  256.             
  257.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  258.             myErr = USBDeviceRequest(pb);
  259.             if(immediateError(myErr))
  260.             {
  261.                 pCompositePB->pb.usbRefcon &= ~kCompletionPending;
  262.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": kSetRemoteWakeup - immediate error", myErr);
  263.             }
  264.             break;
  265.  
  266.         case kNewInterfaceRef:
  267.     debugStatus(pCompositePB->pb.usbReference, ": kNewInterfaceRef new ", pCompositePB->currentInterface);
  268.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  269.             // Note: pCompositePB->usb.cntl.WIndex will be set to zero by InitParamBlock
  270.             // so set it again to pCompositePB->interfaceIndex before calling USBNewInterfaceRef
  271.             pCompositePB->pb.usb.cntl.WIndex = pCompositePB->currentInterface;
  272.             pCompositePB->pb.usbRefcon |= kCompletionPending;
  273.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  274.  
  275.             myErr = USBNewInterfaceRef(pb);
  276.             if(immediateError(myErr))
  277.             {
  278.                 pCompositePB->pb.usbRefcon &= ~kCompletionPending;
  279.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": kNewInterfaceRef - immediate error", myErr);
  280.             }
  281.             break;
  282.  
  283.         case kGetInterfaceDesc:
  284.     debugStatus(pCompositePB->pb.usbReference, ": kGetInterfaceDesc", pCompositePB->interfaces[pCompositePB->interfaceIndex].ref);
  285.             InitParamBlock(pCompositePB->interfaces[pCompositePB->interfaceIndex].ref, &pCompositePB->pb);
  286.             pCompositePB->pb.usb.cntl.WIndex = 0;     // Get me the first one
  287.             pCompositePB->pb.usbOther = kUSBInterfaceDesc;     // Get me an interface descriptor
  288.             pCompositePB->pb.usbBuffer = &pCompositePB->interfaces[pCompositePB->interfaceIndex].desc;     // put it here
  289.             pCompositePB->pb.usbReqCount = sizeof(USBInterfaceDescriptor);     // at most this size
  290.             
  291.             
  292.     debugStatus(pCompositePB->pb.usbReference, ": kGetInterfaceDesc", pCompositePB->interfaces[pCompositePB->interfaceIndex].ref);
  293.     //    *(long *)pCompositePB->pb.usbBuffer = 0;
  294.             
  295.             pCompositePB->pb.usbRefcon |= kCompletionPending;        
  296.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  297.             myErr = USBFindNextAssociatedDescriptor(pb);
  298.             if(immediateError(myErr))
  299.             {
  300.                 pCompositePB->pb.usbRefcon &= ~kCompletionPending;
  301.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": kGetInterfaceDesc - immediate error", myErr);
  302.             }
  303.             
  304.             break;
  305.  
  306.         case kFindNextInterface:
  307.     debugStatus(pCompositePB->pb.usbReference, ": kFindNextInterface curr ", pCompositePB->currentInterface);
  308.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  309.             
  310.             pCompositePB->pb.usb.cntl.WValue = pCompositePB->currentConfiguration;             
  311.             // Find the first configuration with any interface which satisfy the power requirements
  312.             pCompositePB->pb.usbReqCount = newInterfacesPB.busPowerAvailable;             
  313.             pCompositePB->pb.usbClassType = 0;             
  314.             pCompositePB->pb.usbSubclass = 0;             
  315.             pCompositePB->pb.usbProtocol = 0;             
  316.             pCompositePB->pb.usb.cntl.WValue = pCompositePB->currentConfiguration;             
  317.             pCompositePB->pb.usb.cntl.WIndex = pCompositePB->currentInterface;             
  318.             pCompositePB->pb.usbOther = 0xff;         // Find primary interface, not alts
  319.             
  320.             
  321.             pCompositePB->pb.usbRefcon |= kCompletionPending;        
  322.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  323.             myErr = USBFindNextInterface(pb);
  324.             if(immediateError(myErr))
  325.             {
  326.                 pCompositePB->pb.usbRefcon &= ~kCompletionPending;
  327.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": kFindNextInterface - immediate error", myErr);
  328.             }
  329.  
  330.             break;
  331.             
  332.         default:
  333.             USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName" - Transaction initiated with bad refcon value", pCompositePB->pb.usbRefcon);
  334.             pCompositePB->pb.usbRefcon = kUndefined + kReturnFromDriver;
  335.             break;
  336.     }
  337.     
  338. // At this point the control is returned to the system.  If a USB transaction
  339. // has been initiated, then it will call the Complete procs
  340. // (below) to handle the results of the transaction.
  341. }
  342.  
  343. void CompositeDeviceCompletionProc(USBPB *pb)
  344. {
  345. register usbCompositePBStruct *pCompositePB;
  346. static entryCounter = 0;
  347.  
  348.     pCompositePB = (usbCompositePBStruct *)(pb);
  349.  
  350.     if (pCompositePB->expertTerminatePending)                // TCC <USB16>
  351.     {
  352.         pCompositePB->pb.usbRefcon = 0;                        // BT 7/27/00 clear completion pending flag
  353.         return;
  354.     }
  355.     
  356.     if(USB_LOCATION_FLAG && (pCompositePB->pb.usbStatus == kUSBAbortedError))
  357.     {    // This only happens if you're running from ROM. Presumably the expert has aborted you for replacement
  358.         USBExpertStatusLevel(3, pCompositePB->pb.usbReference, kCompositeDriverName" in ROM, abandoning aborted transaction", pCompositePB->pb.usbStatus);
  359.         pCompositePB->pb.usbRefcon = 0;
  360.         return;
  361.     }
  362.         
  363.     pCompositePB->transDepth--;
  364.     if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1))
  365.     {
  366.         USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName" - Illegal Transaction Depth", pCompositePB->transDepth);
  367.     }
  368.     
  369.     
  370.     
  371.     if(pCompositePB->pb.usbStatus == kUSBDevicePowerProblem)
  372.     { 
  373.         if((pCompositePB->pb.usbRefcon & ~(kCompletionPending + kReturnFromDriver)) == kGetAConfiguration)
  374.         {
  375.  
  376.             USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName": sending power note and giving up", pCompositePB->pb.usbStatus);
  377.             
  378.             USBExpertSetDevicePowerStatus(pCompositePB->pb.usbReference, 0, 0, kUSBDevicePower_BusPowerInsufficient, pCompositePB->busPowerAvailable, kUSB500mAAvailable);  // TC: <USB67>
  379.             pCompositePB->pb.usbRefcon = kReturnFromDriver;
  380.             return;
  381.         }
  382.         if((pCompositePB->pb.usbRefcon & ~(kCompletionPending + kReturnFromDriver)) == kSetConfig)
  383.         {
  384.             USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName": kSetConfig gives power problem, must have 0mA to play with", pCompositePB->pb.usbStatus);
  385.             pCompositePB->pb.usbRefcon = kReturnFromDriver;
  386.             return;                    
  387.         }
  388.         USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName": power problem in unexpected state", pCompositePB->pb.usbRefcon);
  389.     }
  390.     
  391.     if ((pCompositePB->pb.usbStatus == kUSBEndpointStallErr) && 
  392.         (pCompositePB->pb.usbRefcon & ~(kCompletionPending + kReturnFromDriver)) == kSetRemoteWakeup){
  393.         USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName": Device does not support RemoteWakeup (should look in the descriptor)", pCompositePB->configDescriptor.attributes);
  394.         pCompositePB->pb.usbStatus = kUSBNoErr;
  395.     }
  396.     
  397.     if((pCompositePB->pb.usbStatus != kUSBNoErr) && (pCompositePB->pb.usbStatus != kUSBPending))
  398.     {
  399.         USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName": Completion Error", pCompositePB->pb.usbStatus);
  400.         pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  401.         pCompositePB->pb.usbRefcon |= kRetryTransaction;
  402.         pCompositePB->retryCount--;
  403.         if (!pCompositePB->retryCount)
  404.         {
  405.             USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": Too many retries", pCompositePB->pb.usbRefcon);
  406.             pCompositePB->pb.usbRefcon = kReturnFromDriver;
  407.             return;
  408.         }
  409.     }
  410.     else
  411.     {
  412.         pCompositePB->pb.usbRefcon &= ~kRetryTransaction;
  413.         pCompositePB->retryCount = kCompositeRetryCount;
  414.     }
  415.  
  416.     if (pCompositePB->pb.usbRefcon & kCompletionPending)             
  417.     {                                                
  418.         pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  419.         switch(pCompositePB->pb.usbRefcon)
  420.         {
  421.             case kResetDevice:            /* Device is not reset */
  422.     debugStatus(pCompositePB->pb.usbReference, ": kResetDevice reset ", newInterfacesPB.busPowerAvailable);
  423.                 pCompositePB->pb.usbRefcon = kGetAConfiguration;
  424.                 break;
  425.  
  426.             case kGetAConfiguration:
  427.     debugStatus(pCompositePB->pb.usbReference, ": kGetAConfiguration got ", pCompositePB->pb.usb.cntl.WValue);
  428.                 // usb.cntl.WValue has the configuration value
  429.                 // usb.cntl.WIndex has the first interface number
  430.                 
  431.                 pCompositePB->currentConfiguration = pCompositePB->pb.usb.cntl.WValue;
  432.                 pCompositePB->currentInterface = pCompositePB->pb.usb.cntl.WIndex;
  433.                 pCompositePB->interfaceIndex = 0;
  434.                 
  435.                 pCompositePB->pb.usbRefcon = kSetConfig;
  436.  
  437.                 break;
  438.                 
  439.             case kSetConfig:
  440.     debugStatus(pCompositePB->pb.usbReference, ": kSetConfig count ", pCompositePB->pb.usbOther);
  441.                 pCompositePB->interfaceCount = pCompositePB->pb.usbOther;
  442.  
  443.                 pCompositePB->pb.usbRefcon = kAllocInterfaces;
  444.                 break;
  445.                 
  446.             case kAllocInterfaces:
  447.                 
  448.                 if(pCompositePB->pb.usbActCount < pCompositePB->interfaceCount * sizeof(interface))
  449.                 {
  450.                     USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName"kAllocInterfaces - not enough memory allocated", pCompositePB->pb.usbActCount);
  451.                     pCompositePB->pb.usbRefcon = kReturnFromDriver;
  452.                 }
  453.                 else
  454.                 {
  455.                     pCompositePB->interfaces = pCompositePB->pb.usbBuffer;
  456.                     pCompositePB->pb.usbRefcon = kGetConfigDesc;
  457.                 }
  458.                 break;
  459.  
  460.             case kGetConfigDesc:
  461.     debugStatus(pCompositePB->pb.usbReference, ": kGetConfigDesc ", pCompositePB->pb.usbActCount);
  462.                 if(pCompositePB->pb.usbActCount < kUSBConfigDescriptorLength)
  463.                 {
  464.                     USBExpertStatusLevel(2, pCompositePB->pb.usbReference, kCompositeDriverName": kGetConfigDesc - got bad descriptor", pCompositePB->pb.usbActCount);
  465.                     pCompositePB->pb.usbRefcon = kNewInterfaceRef;
  466.                 }
  467.                 else
  468.                 {
  469.                     pCompositePB->pb.usbRefcon = 
  470.                         (pCompositePB->configDescriptor.attributes & kUSBAtrRemoteWakeup) ? kSetRemoteWakeup : kNewInterfaceRef;
  471.                 }            
  472.                 break;
  473.             
  474.  
  475.             case kSetRemoteWakeup:            
  476.     debugStatus(pCompositePB->pb.usbReference, ": kSetRemoteWakeup ", pCompositePB->pb.usbReference);
  477.                 pCompositePB->pb.usbRefcon = kNewInterfaceRef;
  478.                 break;
  479.                 
  480.             case kNewInterfaceRef:
  481.                     pCompositePB->pb.usbRefcon = kReturnFromDriver;
  482.                 /* save the new interface ref for this interface */
  483.     debugStatus(pCompositePB->pb.usbReference, ": kNewInterfaceRef ", pCompositePB->pb.usbReference);
  484.                 pCompositePB->interfaces[pCompositePB->interfaceIndex].ref = pCompositePB->pb.usbReference;
  485.                 
  486.                 pCompositePB->pb.usbRefcon = kGetInterfaceDesc;
  487.                 break;                
  488.  
  489.             case kGetInterfaceDesc:
  490.     debugStatus(pCompositePB->pb.usbReference, ": kGetInterfaceDesc result", *(long *)pCompositePB->pb.usbBuffer);
  491.  
  492.                 if(pCompositePB->pb.usbActCount < kUSBInterfaceDescriptorLength)
  493.                 {
  494.                     USBExpertStatusLevel(2, pCompositePB->pb.usbReference, kCompositeDriverName": kGetInterfaceDesc - got bad descriptor", pCompositePB->pb.usbActCount);
  495.                 }
  496.                 else
  497.                 {
  498.                 //    pCompositePB->interfaces[pCompositePB->interfaceIndex].desc = *(USBInterfaceDescriptor *)pCompositePB->pb.usbBuffer;
  499.                     USBExpertInstallInterfaceDriver(pCompositePB->interfaces[pCompositePB->interfaceIndex].ref, 
  500.                         &pCompositePB->deviceDescriptor, pCompositePB->pb.usbBuffer, pCompositePB->deviceRef, 0);
  501.                 }
  502.                 
  503.                 /* if there's more interfaces, find them */
  504.                 pCompositePB->interfaceIndex++;
  505.                 if (pCompositePB->interfaceIndex < pCompositePB->interfaceCount)
  506.                 {
  507.                     pCompositePB->pb.usbRefcon = kFindNextInterface;
  508.                 }
  509.                 else
  510.                 {
  511.                     pCompositePB->interfacesRead = true;
  512.                     pCompositePB->pb.usbRefcon = kReturnFromDriver;
  513.                 }
  514.                 break;
  515.  
  516.             case kFindNextInterface:
  517.                 if(pCompositePB->currentConfiguration != pCompositePB->pb.usb.cntl.WValue)
  518.                 {
  519.                     USBExpertStatusLevel(2, pCompositePB->pb.usbReference, kCompositeDriverName": kFindNextInterface - Interface found is not in correct configuration", pCompositePB->pb.usb.cntl.WValue);
  520.                     pCompositePB->pb.usbRefcon = kReturnFromDriver;
  521.                 }
  522.                 else
  523.                 {
  524.                     pCompositePB->currentInterface = pCompositePB->pb.usb.cntl.WIndex;
  525.                     pCompositePB->pb.usbRefcon = kNewInterfaceRef;
  526.                 }
  527.  
  528.                 break;
  529.                 
  530.             default:
  531.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName" - Transaction completed with a bad refcon value", pCompositePB->pb.usbRefcon);
  532.                 pCompositePB->pb.usbRefcon = kReturnFromDriver;
  533.                 break;
  534.         }
  535.     }
  536.  
  537.     if ( !(pCompositePB->pb.usbRefcon & kReturnFromDriver) && (!pCompositePB->driverRemovalPending))
  538.     {
  539.         CompositeDeviceInitiateTransaction(pb);
  540.     }
  541.  
  542. }
  543.  
  544. // entry points, moved from CompositeDriverDescription.c
  545.  
  546. // hubDriverInitInterface function
  547. // Called to initialize driver for an individual interface - either by expert or
  548. // internally by driver
  549. OSStatus CompositeDriverInitInterface(
  550.             UInt32                         interfaceNum, 
  551.             USBInterfaceDescriptor        *interfaceDesc, 
  552.             USBDeviceDescriptor            *deviceDesc, 
  553.             USBDeviceRef                 device)
  554. {
  555. #pragma unused (interfaceNum)
  556. #pragma unused (interfaceDesc)
  557. #pragma unused (deviceDesc)
  558. #pragma unused (device)
  559.  
  560.     return (OSStatus)kUSBNoErr;
  561. }
  562.  
  563.  
  564. static OSStatus removeInterfaces(void)
  565. {
  566. OSStatus    myErr;
  567. OSStatus     status = kUSBNoErr;
  568. static    UInt32    interfacenum = 0;
  569.  
  570.     newInterfacesPB.driverRemovalPending = true;
  571.     
  572.     if (interfacenum == 0)
  573.         newInterfacesPB.pb.usbStatus = kUSBNoErr;
  574.     
  575.     if (newInterfacesPB.pb.usbStatus == kUSBPending)
  576.     {
  577.         USBExpertStatusLevel(5, newInterfacesPB.deviceRef, kCompositeDriverName": Waiting for Dispose/Deallocate to complete", newInterfacesPB.pb.usbRefcon);
  578.         status = kUSBInternalErr;
  579.     }
  580.     else
  581.     {
  582.         if (interfacenum < newInterfacesPB.interfaceCount)        
  583.         {
  584.             USBExpertRemoveInterfaceDriver(newInterfacesPB.interfaces[interfacenum].ref);
  585.             InitParamBlock(newInterfacesPB.interfaces[interfacenum].ref, &newInterfacesPB.pb);
  586.             newInterfacesPB.pb.usbRefcon = 0;             
  587.             newInterfacesPB.pb.usbCompletion = (USBCompletion)kUSBNoCallBack;
  588.             myErr = USBDisposeInterfaceRef(&newInterfacesPB.pb);
  589.             if(immediateError(myErr))
  590.             {
  591.                 USBExpertFatalError(newInterfacesPB.interfaces[interfacenum].ref, kUSBInternalErr, kCompositeDriverName" - USBDisposeInterfaceRef - immediate error", myErr);
  592.             }
  593.             interfacenum++;
  594.             status = kUSBDeviceBusy;
  595.         }
  596.         else
  597.         {
  598.             if (newInterfacesPB.interfaces)
  599.             {
  600.                 InitParamBlock(newInterfacesPB.deviceRef, &newInterfacesPB.pb);
  601.                 newInterfacesPB.pb.usbRefcon = 0;             
  602.                 newInterfacesPB.pb.usbBuffer = newInterfacesPB.interfaces;        
  603.                 newInterfacesPB.pb.usbCompletion = (USBCompletion)kUSBNoCallBack;
  604.                 myErr = USBDeallocMem(&newInterfacesPB.pb);
  605.                 if(myErr != noErr)
  606.                 {
  607.                     USBExpertStatus(newInterfacesPB.deviceRef, kCompositeDriverName": error disposing descriptors", myErr);
  608.                 }
  609.                 newInterfacesPB.interfaces = nil;
  610.             }
  611.             interfacenum = 0;    // Ready for next time
  612.             status = noErr;
  613.         }
  614.     }
  615.     return(status);
  616. }
  617.  
  618. OSStatus    CompositeDriverNotifyProc(UInt32     notification, void *pointer, UInt32 refcon)
  619. {
  620. OSStatus     status = kUSBNoErr;
  621. UInt32        count = 0;
  622. USBPB *pb;
  623.  
  624.     switch (notification)
  625.     {
  626.         case kNotifyChildMessage:
  627.             USBExpertStatus(newInterfacesPB.deviceRef, kCompositeDriverName": child message from", refcon);
  628.             pb = pointer;
  629.             if (newInterfacesPB.pb.usbRefcon & kCompletionPending)
  630.             {
  631.                 USBExpertStatusLevel(3, newInterfacesPB.deviceRef, kCompositeDriverName": busy for child message", pb->usb.hub.Request);
  632.                 status = kUSBDeviceBusy;
  633.             }
  634.             else
  635.             {
  636.                 if(pb->usb.hub.Request == kUSBHubPortResetRequest)
  637.                 {
  638.                     newInterfacesPB.expertTerminatePending = true;
  639.                     do{
  640.     debugStatus(newInterfacesPB.deviceRef, kCompositeDriverName", Reset: Removing interfaces", 0);
  641.                         status = removeInterfaces();
  642.                     }while(status == kUSBDeviceBusy);
  643.                     
  644.                     if(status == noErr)
  645.                     {
  646.     debugStatus(newInterfacesPB.deviceRef, kCompositeDriverName", Reset: Interfaces removed", 0);
  647.                         newInterfacesPB.expertTerminatePending = false;
  648.                         newInterfacesPB.driverRemovalPending = false;
  649.                         newInterfacesPB.pb.usbRefcon = kResetDevice;            /* Start out at first state */
  650.                         CompositeDeviceInitiateTransaction(&newInterfacesPB.pb);
  651.                     }
  652.                     else
  653.                     {
  654.                         USBExpertStatusLevel(1, newInterfacesPB.deviceRef, kCompositeDriverName": error during driver remove", status);
  655.                     }
  656.                 }
  657.                 else
  658.                 if(pb->usb.hub.Request == kUSBHubPortSuspendRequest)
  659.                 {
  660.                     if(newInterfacesPB.interfaceCount > 1)
  661.                     {
  662.                         USBExpertStatusLevel(3, newInterfacesPB.deviceRef, kCompositeDriverName": could not suspend with multipleinterfaces", newInterfacesPB.interfaceCount);                        
  663.                         status = kUSBUnknownDeviceErr;
  664.                     }
  665.                     else
  666.                     {
  667.                         USBExpertStatusLevel(3, newInterfacesPB.deviceRef, kCompositeDriverName": passing single suspend request up", newInterfacesPB.interfaceCount);                        
  668.                         // If there is one interface, send this message to parent of the composite device (hub)
  669.                         status = kUSBUnknownRequestErr;    // Use this as a signal to tel USL to send it on
  670.                     }
  671.                 }
  672.                 else
  673.                 {
  674.                     USBExpertStatusLevel(1, newInterfacesPB.deviceRef, kCompositeDriverName": unknown child message", pb->usb.hub.Request);
  675.                     status = kUSBUnknownRequestErr;
  676.                 }
  677.             }
  678.         
  679.             break;
  680.  
  681.             
  682.         case kNotifyExpertTerminating:                                // TCC <USB15>
  683.                 newInterfacesPB.expertTerminatePending = true;
  684.                 while (count < newInterfacesPB.interfaceCount)
  685.                         USBExpertRemoveInterfaceDriver(newInterfacesPB.interfaces[count++].ref);
  686.                 return(noErr);
  687.             break;
  688.         case kNotifyDriverBeingRemoved:
  689.             newInterfacesPB.driverRemovalPending = true;
  690.             
  691.             if (newInterfacesPB.pb.usbRefcon & kCompletionPending)
  692.             {
  693.             static UInt32 noted;
  694.                 if(isPowerOf10(noted++))
  695.                 {
  696.                     USBExpertStatus(newInterfacesPB.deviceRef, kCompositeDriverName": Waiting for transaction to complete", newInterfacesPB.pb.usbRefcon);
  697.                 }
  698.                 USBAbortPipeByReference(newInterfacesPB.deviceRef);    // BT 7/27/00 Seems like a good idea.
  699.                 status = kUSBDeviceBusy;
  700.             }
  701.             else
  702.             {
  703.                 status  = removeInterfaces();
  704.             }
  705.             break;
  706.             
  707.         default:
  708.             break;
  709.     }
  710.     return status;
  711. }
  712.  
  713. // Hardware Validation
  714. // Called upon load by Expert
  715. OSStatus CompositeDriverValidateHW(USBDeviceRef device, USBDeviceDescriptor *desc)
  716. {
  717. #pragma unused (device)
  718. #pragma unused (desc)
  719.  
  720.     return (OSStatus)kUSBNoErr;
  721. }
  722.  
  723. // Initialization function
  724. // Called upon load by Expert
  725. OSStatus     CompositeDriverInitialize (USBDeviceRef device, USBDeviceDescriptorPtr pDesc,  UInt32 busPowerAvailable)
  726. {
  727.     // don't let a race condition occur; prevent finalizing until we're all done.
  728.     DeviceInitialize(device, pDesc, busPowerAvailable);
  729.     return (OSStatus)kUSBNoErr;
  730. }
  731.  
  732. // Termination function
  733. // Called by Expert when driver is being shut down
  734. OSStatus CompositeDriverFinalize(USBDeviceRef theDeviceRef, USBDeviceDescriptorPtr pDesc)
  735. {
  736. #pragma unused (pDesc)
  737.  
  738.     USBExpertStatus(theDeviceRef, kCompositeDriverName" - Finalize", 0);
  739.     return (OSStatus)kUSBNoErr;
  740. }
  741.  
  742. void DeviceInitialize(USBDeviceRef device, USBDeviceDescriptorPtr pDeviceDescriptor, UInt32 busPowerAvailable)
  743. {
  744. static Boolean beenThereDoneThat = false;
  745. UInt32 errataBits;
  746.  
  747.     if(beenThereDoneThat)
  748.     {
  749.         USBExpertFatalError(device, kUSBInternalErr, kCompositeDriverName" is not reentrant!", 0);
  750.         return;
  751.     }
  752.     
  753.     if(USB_LOCATION_FLAG)
  754.     {
  755.         USBExpertStatusLevel(4, device, kCompositeDriverName" running out of ROM:", USB_LOCATION_FLAG);
  756.     }
  757.     
  758.     beenThereDoneThat = true;
  759.     
  760.     newInterfacesPB.driverRemovalPending = false;
  761.     newInterfacesPB.expertTerminatePending = false;
  762.     
  763.     newInterfacesPB.deviceRef = device;    
  764.     newInterfacesPB.deviceDescriptor = *pDeviceDescriptor;    
  765.     
  766.     newInterfacesPB.busPowerAvailable = busPowerAvailable;                            
  767.     newInterfacesPB.delayLevel = 0;                            
  768.     newInterfacesPB.transDepth = 0;                            
  769.     newInterfacesPB.retryCount = kCompositeRetryCount;
  770.     
  771.     InitParamBlock(device, &newInterfacesPB.pb);
  772.  
  773.     errataBits = GetErrataBits(pDeviceDescriptor);
  774.     if(errataBits != 0)
  775.     {
  776.         USBExpertStatusLevel(3, device, kCompositeDriverName"Using errata:", errataBits);
  777.     }
  778.  
  779.     if((USBGetVersion() & 0xfff00000) == 0x01300000)    // 1.3.(5|6) had the hub reset memory corruption bug
  780.     {                                        // refuse to run mismatched and ROM driver will be used.
  781.         USBExpertStatusLevel(1,device, kCompositeDriverName" - DeviceInitialize not resetting due to version conflict", USBGetVersion());
  782.         USBExpertStatusLevel(1,device, "\pUSB Device Extension is not paired with correct USB Support, USB may be flaky", 0);
  783.         errataBits |= kErrataNoReset;
  784.     }
  785.  
  786.  
  787.     if( (errataBits & kErrataNoReset) != 0)
  788.     {
  789.         newInterfacesPB.pb.usbRefcon = kGetAConfiguration;    /* Start out at first state which isn't reset */
  790.     }
  791.     else
  792.     {
  793.         newInterfacesPB.pb.usbRefcon = kResetDevice;            /* Start out at first state */
  794.     }
  795.     
  796. //    DebugStr("\pIn Composite Driver");
  797.     CompositeDeviceInitiateTransaction(&newInterfacesPB.pb);
  798. }
  799.  
  800.  
  801.